/* Copyright (C) 2009 Mobile Sorcery AB

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License, version 2, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/

#include <SDL/SDL_net.h>
#include <vector>
#include <string>
#include <map>
#include <stdlib.h>
#include <string.h>
#include <fstream>



// for cwd
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>

#endif

using namespace std;

string workingdir;

string integerToString(int i) {
	char temp[16];
//	itoa(i, temp, 10);
	sprintf(temp, "%d", i);
	return temp;
}

char *readFileIntoMem(const char* filename, int *len) {
	FILE *file = fopen(filename, "rb");
	if(!file) return NULL;
	fseek(file, 0, SEEK_END);
	int length = ftell(file);
	fseek(file, 0, SEEK_SET);
	char *memory = new char[length];
	fread(memory, length, 1, file);
	fclose(file);
	*len = length;
	return memory;
}

bool writeMemIntoFile(const char* filename, const char *mem, int len) {
	FILE *file = fopen(filename, "wb");
	if(!file) return false;
	fwrite(mem, len, 1, file);
	fclose(file);
	return true;
}

void replaceTemplateDefine(string &templateFile, const string &whatToReplace, const string &replacement) {
	size_t index;
	while((index=templateFile.find(whatToReplace))!=string::npos) {
		int endOfReplacement = index+whatToReplace.length();
		templateFile = templateFile.substr(0, index) + replacement + templateFile.substr(endOfReplacement, templateFile.size()-endOfReplacement);
	}
}

void error(const char *s) {
	printf("%s\n", s);
}

string mosyncdir;

TCPsocket initListeningSocket(int port) {
	TCPsocket sd; /* Socket descriptor, Client socket descriptor */
	IPaddress ip;
 
	/* Resolving the host using NULL make network interface to listen */
	if (SDLNet_ResolveHost(&ip, NULL, port) < 0)
	{
		fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
		exit(EXIT_FAILURE);
	}
 
	/* Open a connection with the IP provided (listen on the host's port) */
	if (!(sd = SDLNet_TCP_Open(&ip)))
	{
		fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
		exit(EXIT_FAILURE);
	}

	return sd;
}

void closeListeningSocket(TCPsocket sd) {
	SDLNet_TCP_Close(sd);	
}

/*
void splitCommands(vector<string>& commands, const char* src) {
	char *lastCommand;
	char *src = command;
	while(*src) {
		while(*src && *src==' ') src++;
		if(!*src) break;
		lastCommand = src;
		while(*src && *src!=' ') src++;
		if(*src) {
			*src = 0;
			src++;
		}
		commands.push_back(lastCommand);
	}
}
*/

int recieveCommand(char *command) {
	printf(">");
	char data[1024];
	gets(data);
	if(strncmp(data, "exit", 4)==0 || strncmp(data, "quit", 4)==0) return -1;
	
	int len = strlen(data);
	
	if(strncmp(data, "eval ", 5) == 0) {		
		strcpy(command, &data[5]);
		return len - 5;
	}
	else if(strncmp(data, "loadScript ", 11) == 0) {
		int fileLength = -2;
		const char* filename = &data[11];
		printf("Trying to load file \"%s\"\n", filename);		
		char *file = readFileIntoMem(filename, &fileLength);
		if(!file) 
			return -2;
		printf("Loaded file \"%s\" with length %d\n", filename, fileLength);	
		memcpy(command, file, fileLength);
		delete file;
		return fileLength;
	}
	
	return -2;
}

bool recieveDone(TCPsocket client) {
	char recvBuf[256];
	SDLNet_TCP_Recv(client, recvBuf, 256);
	if(strncmp(recvBuf, "done", 4) != 0) {
		//printf("Something went wrong with the response.\n");
		return false;
	}
	return true;
}

/*
bool loadScript(vector<string>& commands, const string& filename) {
	FILE *file = fopen(filename.c_str(), "r");
	if(!file) return false;

	commands.clear();
	char command[256];	
	
	while(fgets(command, 256, file)) {
		splitCommands(commands, command); 
	}
	
	if(feof(file))
		return true;
	else
		return false;
}
*/

bool mainLoop(TCPsocket sd) {
	TCPsocket client;
	IPaddress *remoteIP;
	char command[16*1024];

	printf("waiting for client..\n");

	while(!(client = SDLNet_TCP_Accept(sd))) {};

	{
			if ((remoteIP = SDLNet_TCP_GetPeerAddress(client))) {
				printf("connected to client..\n");
				int commandLength = 0;
				while((commandLength = recieveCommand(command)) != -1) {
					if(commandLength == -2) {
						printf("Invalid command!\n");
						continue;
					}
					SDLNet_TCP_Send(client, (void*)&commandLength, sizeof(int));
					SDLNet_TCP_Send(client, command, commandLength);
					if(!recieveDone(client)) {
						printf("Something went wrong with the response.\n");
					}
				}
			}
	}
	return true;
}

int main(int argc, char **argv) {
	if (SDLNet_Init() < 0)
	{
		fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
		exit(EXIT_FAILURE);
	}

	TCPsocket sd = initListeningSocket(8080);

	const char *c= getenv("MOSYNCDIR");
	if(!c) { error("no MOSYNCDIR"); return 1; }
	mosyncdir = c;

	workingdir.resize(256);
#ifdef _WIN32
	::GetCurrentDirectoryA(256, &workingdir[0]);
#else
	 getcwd(&workingdir[0], 256);
#endif
	workingdir.resize(strlen(&workingdir[0]));

	printf("Working directory: %s\n", workingdir.c_str());

	while(mainLoop(sd)) {}

	closeListeningSocket(sd);
	
	SDLNet_Quit();

	return 0;
}